`timescale 1ns/100ps

`include "sim_glb.sv"
`include "public_head.sv"

module tc;

localparam          CLK_PRD                 = 5;

reg                                         rst_n;
reg                                         clk;
wire                                        rst_cfg_n;
wire                [1-1:0]                 fifo_ilf_eis;
wire                [1-1:0]                 fifo_ilf_ie;
reg                 [1-1:0]                 fifo_ilf_ois;
wire                [1-1:0]                 fifo_ilf_ois_hst;
reg                                         cnt_rx_good_octet_ce;
reg                 [13-1:0]                cnt_rx_good_octet_inc;
reg                                         cnt_rx_cmd_ce;
reg                                         cnt_tx_cmd_ce;
wire                [1-1:0]                 mem_rw_start;
wire                [1-1:0]                 mem_rw_type;
wire                [1-1:0]                 mem_rw_b2b;
wire                                        mem_rw_addr_bwe;
wire                [12-1:0]                mem_rw_addr_bwd;
wire                [12-1:0]                mem_rw_addr;
wire                                        mem_rw_addr_fwe;
wire                                        iaa_ctrl_fwe;   // forward write enable for CTRL(b2b/wr/start/addr) reg
wire                                        iaa_data_frw;   // forward read and write for DATA reg
wire                [1-1:0]                 mem_rw_miss;
wire                [1-1:0]                 mem_rw_busy;
wire                                        mem_rw_data_bwe;
wire                [32-1:0]                mem_rw_data_bwd;
wire                [32-1:0]                mem_rw_data;
wire                                        mem_rw_data_fwe;
wire                                        mem_rw_data_fre;
wire                [32-1:0]                disable_cfg;
wire                                        disable_cfg_fwe;
reg                 [1-1:0]                 auto_req_clr;
wire                [1-1:0]                 auto_req;
wire                [1-1:0]                 phy_reset;
reg                 [4-1:0]                 link_err;
reg                 [4-1:0]                 phy_err;
reg                                         scnt_wcmd_1berr_ce;
reg                                         scnt_rcmd_1berr_ce;
reg                 [16-1:0]                fifo_cnt_max;
reg                 [16-1:0]                fifo_cnt_min;
reg                 [32-1:0]                grp_ext;
wire                                        grp_ext_fwe;
wire                                        grp_ext_fre;

wire                                        rab_en;
wire                                        rab_wr;
wire                [12-1:0]                rab_addr;
wire                [32-1:0]                rab_wdat;
wire                [32-1:0]                rab_rdat;
wire                                        rab_busy;

wire                                        mem_req;
wire                                        mem_wr;
wire                [12-1:0]                mem_addr;
wire                [32-1:0]                mem_wdat;
wire                [32-1:0]                mem_rdat;   // rdat is valid after MEM_RL from mem_ack for read
wire                                        mem_ack;
wire                                        mem_wen;
wire                                        mem_ren;

wire                                        int2cpu;

initial begin:CRG
    rst_n=1'b0;
    clk=1'b0;

    fork
        rst_n=#100.5 1'b1;
        forever clk=#CLK_PRD ~clk;
    join
end
assign rst_cfg_n = rst_n;

RGRS_MNG    rgrs;
initial begin:REGRESS
    rgrs = new("tc_xxx_regs", 1);

    rgrs.wait_chks_done(100_000_000);
end

xxx_regs u_xxx_regs (
        .rst_n                          (rst_n                          ),
        .rst_cfg_n                      (rst_cfg_n                      ),
        .clk                            (clk                            ),

        .fifo_ilf_eis                   (fifo_ilf_eis                   ),
        .fifo_ilf_ie                    (fifo_ilf_ie                    ),
        .fifo_ilf_ois                   (fifo_ilf_ois                   ),
        .fifo_ilf_ois_hst               (fifo_ilf_ois_hst               ),
        .cnt_rx_good_octet_ce           (cnt_rx_good_octet_ce           ),
        .cnt_rx_good_octet_inc          (cnt_rx_good_octet_inc          ),
        .cnt_rx_cmd_ce                  (cnt_rx_cmd_ce                  ),
        .cnt_tx_cmd_ce                  (cnt_tx_cmd_ce                  ),
        .mem_rw_start                   (mem_rw_start                   ),
        .mem_rw_type                    (mem_rw_type                    ),
        .mem_rw_b2b                     (mem_rw_b2b                     ),
        .mem_rw_addr_bwe                (mem_rw_addr_bwe                ),
        .mem_rw_addr_bwd                (mem_rw_addr_bwd                ),
        .mem_rw_addr                    (mem_rw_addr                    ),
        .mem_rw_addr_fwe                (mem_rw_addr_fwe                ),
        .mem_rw_addr_fre                (                               ),
        .mem_rw_miss                    (mem_rw_miss                    ),
        .mem_rw_busy                    (mem_rw_busy                    ),
        .mem_rw_data_bwe                (mem_rw_data_bwe                ),
        .mem_rw_data_bwd                (mem_rw_data_bwd                ),
        .mem_rw_data                    (mem_rw_data                    ),
        .mem_rw_data_fwe                (mem_rw_data_fwe                ),
        .mem_rw_data_fre                (mem_rw_data_fre                ),
        .disable_cfg                    (disable_cfg                    ),
        .disable_cfg_fwe                (disable_cfg_fwe                ),
        .auto_req_clr                   (auto_req_clr                   ),
        .auto_req                       (auto_req                       ),
        .phy_reset                      (phy_reset                      ),
        .link_err                       (link_err                       ),
        .phy_err                        (phy_err                        ),
        .scnt_wcmd_1berr_ce             (scnt_wcmd_1berr_ce             ),
        .scnt_rcmd_1berr_ce             (scnt_rcmd_1berr_ce             ),
        .fifo_cnt_max                   (fifo_cnt_max                   ),
        .fifo_cnt_min                   (fifo_cnt_min                   ),
        .grp_ext                        (grp_ext                        ),
        .grp_ext_fwe                    (grp_ext_fwe                    ),
        .grp_ext_fre                    (grp_ext_fre                    ),

        .rab_en                         (rab_en                         ),
        .rab_wr                         (rab_wr                         ),
        .rab_addr                       (rab_addr                       ),
        .rab_wdat                       (rab_wdat                       ),
        .rab_rdat                       (rab_rdat                       ),
        .rab_busy                       (rab_busy                       )
);

assign iaa_ctrl_fwe = mem_rw_addr_fwe;
assign iaa_data_frw = mem_rw_data_fwe | mem_rw_data_fre;

iaa2mem #(      // indirect address access(read/write) memory
        .DEPTH                          (2050                           ),
        .DATA_BW                        (32                             ),
        .INC_BW                         (1                              ),	// address increment bit width
        .MEM_RL                         (3                              ) 	// meory read latency
) u_iaa2mem ( 
        .rst_n                          (rst_n                          ),
        .clk                            (clk                            ),

        .iaa_b2b                        (mem_rw_b2b                     ),	// 0:single RW; 1: fast RW back-to-back;
        .iaa_wr                         (mem_rw_type                    ),	// 1'b1: wtite; 1'b0: read
        .iaa_start                      (mem_rw_start                   ),	// 1 clock pulse to start a single RW
        .iaa_addr                       (mem_rw_addr                    ),
        .iaa_addr_bwe                   (mem_rw_addr_bwe                ),
        .iaa_addr_bwd                   (mem_rw_addr_bwd                ),
        .iaa_data                       (mem_rw_data                    ),	// write data CPU -> mem
        .iaa_data_fwe                   (mem_rw_data_fwe                ),
        .iaa_data_fre                   (mem_rw_data_fre                ),
        .iaa_data_bwe                   (mem_rw_data_bwe                ),
        .iaa_data_bwd                   (mem_rw_data_bwd                ),	// read data CPU <- mem
        .iaa_addr_inc                   (1'b1                           ),	// address increment at back-to-back mode
        .iaa_ctrl_fwe                   (iaa_ctrl_fwe                   ),	// forward write enable for CTRL(b2b/wr/start/addr) reg
        .iaa_data_frw                   (iaa_data_frw                   ),	// forward read and write for DATA reg
        .iaa_miss                       (mem_rw_miss                    ),	// mem_ack must fast enough avoid to miss next RW
        .iaa_busy                       (mem_rw_busy                    ),

        .mem_req                        (mem_req                        ),
        .mem_wr                         (mem_wr                         ),
        .mem_addr                       (mem_addr                       ),
        .mem_wdat                       (mem_wdat                       ),
        .mem_rdat                       (mem_rdat                       ),	// rdat is valid after MEM_RL from mem_ack for read
        .mem_ack                        (mem_ack                        )
);

assign mem_ack = mem_req;
assign mem_wen = mem_req & mem_wr;
assign mem_ren = mem_req & (~mem_wr);

spram_wrap #(
        .DEPTH                          (2050                           ),
        .DATA_BW                        (32                             ),
        .RDPL_NUM                       (3                              ),	// Read Data Pipe Line number, MUST >=1
        .USER_DEF_TAG                   ("NONE"                         ),
        .ECC_MODE                       ("NONE"                         ) 	// no ECC
) u_mem ( 
        .rst_n                          (rst_n                          ),
        .clk                            (clk                            ),

        .mem_wen                        (mem_wen                        ),
        .mem_ren                        (mem_ren                        ),
        .mem_rce                        ({3{1'b1}}                      ),
        .mem_addr                       (mem_addr                       ),
        .mem_wdat                       (mem_wdat                       ),
        .mem_rvld                       (                               ),
        .mem_rdat                       (mem_rdat                       ),

        .cfg_frc_sbe                    (1'b0                           ),	// support at ECC_MODE
        .alm_ecc_err                    (                               ),	// support at ECC_MODE
        .alm_ecc_dbe                    (                               )	// support at ECC_MODE
);

int_mux #(
        .INT_NUM                        (1                              ),
        .INT_LEVEL                      (1'b0                           )	// 1'b0:low level trigger interrupt; 1'b1:hight level trigger interrupt;
) u_int_mux ( 
        .rst_n                          (rst_n                          ),
        .clk                            (clk                            ),

        .ie                             ({fifo_ilf_ie}                  ),	// interrupt enable configuration
        .ois                            ({fifo_ilf_ois_hst}             ),	// original interrupt status from alarm/error(through INT_WC) or state(no INT_WC)
        .eis                            ({fifo_ilf_eis}                 ),	// enabled interrupt status(to RO) for CPU checking

        .int2cpu                        (int2cpu                        )
);

rab_it #(12, 32) cpu_rab(clk);
assign rab_en   = cpu_rab.en;
assign rab_wr   = cpu_rab.wr;
assign rab_addr = cpu_rab.addr;
assign rab_wdat = cpu_rab.wdat;
assign cpu_rab.rdat = rab_rdat;
assign cpu_rab.busy = rab_busy;

initial begin:RAB_RW
    integer i;
    logic [31:0] rdat;

    fifo_ilf_ois        = 0;
    cnt_rx_good_octet_ce    = 0;
    cnt_rx_good_octet_inc   = 0;
    cnt_rx_cmd_ce           = 0;
    cnt_tx_cmd_ce           = 0;
    link_err                = 0;
    phy_err                 = 0;
    scnt_wcmd_1berr_ce      = 0;
    scnt_rcmd_1berr_ce      = 0;
    fifo_cnt_max            = 0;
    fifo_cnt_min            = 'hffff;
    grp_ext                 = 'h5678_1234;
    auto_req_clr            = 1'b0;

    @(posedge rst_n);

    cpu_rab.wr_reg_t(10, 12'h104, 32'h0000_0000);
    cpu_rab.rd_reg_t( 1, 12'h100, rdat);
    fifo_ilf_ois = 1'b1;
    @(posedge clk);
    fifo_ilf_ois = 1'b0;
    cpu_rab.rd_reg_t( 1, 12'h100, rdat);
    cpu_rab.rd_reg_t( 1, 12'h108, rdat);
    cpu_rab.wr_reg_t( 1, 12'h108, 32'h0000_0001);

    cnt_rx_good_octet_ce  <=`U_DLY 1;
    cnt_rx_good_octet_inc <=`U_DLY 'h100;
    @(posedge clk);
    cpu_rab.rd_reg_t( 1, 12'h120, rdat);
    cpu_rab.rd_reg_t( 1, 12'h124, rdat);
    @(posedge clk);
    cnt_rx_good_octet_ce  <=`U_DLY 0;
    cnt_rx_good_octet_inc <=`U_DLY 100;
    cpu_rab.rd_reg_t( 1, 12'h120, rdat);
    cpu_rab.rd_reg_t( 1, 12'h124, rdat);

    cnt_rx_cmd_ce <=`U_DLY 1;
    @(posedge clk);
    cnt_tx_cmd_ce <=`U_DLY 1;
    @(posedge clk);
    cnt_rx_cmd_ce <=`U_DLY 0;
    @(posedge clk);
    @(posedge clk);
    cpu_rab.rd_reg_t( 1, 12'h12C, rdat);
    cnt_tx_cmd_ce <=`U_DLY 0;
    cpu_rab.rd_reg_t( 1, 12'h12C, rdat);
    cpu_rab.wr_reg_t( 1, 12'h12c, 32'h0001_0000);
    cpu_rab.rd_reg_t( 1, 12'h12C, rdat);

    @(posedge clk);
    cpu_rab.wr_reg_t( 1, 12'hA00, 32'h8765_4321);
    cpu_rab.wr_reg_t( 1, 12'hABC, 32'h0000_0100);
    link_err <=`U_DLY 'h6;
    phy_err  <=`U_DLY 'ha;
    @(posedge clk);
    link_err <=`U_DLY 'h0;
    phy_err  <=`U_DLY 'h0;
    cpu_rab.rd_reg_t( 1, 12'hABC, rdat);
    cpu_rab.rd_reg_t( 1, 12'hABC, rdat);
    cpu_rab.wr_reg_t( 1, 12'hABC, 32'h0000_00F0);
    cpu_rab.rd_reg_t( 1, 12'hABC, rdat);

    scnt_wcmd_1berr_ce <=`U_DLY 1;
    @(posedge clk);
    scnt_rcmd_1berr_ce <=`U_DLY 1;
    @(posedge clk);
    cpu_rab.rd_reg_t(10, 12'hAC0, rdat);
    scnt_wcmd_1berr_ce <=`U_DLY 0;
    scnt_rcmd_1berr_ce <=`U_DLY 0;
    cpu_rab.wr_reg_t( 1, 12'hAC0, 32'h0000_0008);
    cpu_rab.rd_reg_t( 1, 12'hAC0, rdat);

    fifo_cnt_max <=`U_DLY 100;
    fifo_cnt_min <=`U_DLY 'hff00;
    @(posedge clk);
    fifo_cnt_max <=`U_DLY 99;
    fifo_cnt_min <=`U_DLY 'hff01;
    cpu_rab.rd_reg_t( 1, 12'hAC4, rdat);
    cpu_rab.rd_reg_t( 1, 12'hAC4, rdat);

    cpu_rab.rd_reg_t( 1, 12'hAD0, rdat);
    cpu_rab.wr_reg_t( 1, 12'hAD0, 32'hD000_0008);

    @(posedge clk);
    cpu_rab.wr_reg_t( 1, 12'h130, {1'b0, 1'b1, 1'b0, 17'b0, 12'h789});

    cpu_rab.wr_reg_t( 1, 12'h138, 32'hDADB_DCDD);
    cpu_rab.wr_reg_t( 1, 12'h130, {1'b1, 1'b1, 1'b0, 17'b0, 12'h789});

    cpu_rab.wr_reg_t( 1, 12'h138, 32'h1234_5678);
    cpu_rab.wr_reg_t( 1, 12'h130, {1'b1, 1'b1, 1'b0, 17'b0, 12'h78a});

    cpu_rab.wr_reg_t( 1, 12'h130, {1'b1, 1'b0, 1'b0, 17'b0, 12'h789});
    @(posedge clk);
    @(posedge clk);
    @(posedge clk);
    @(posedge clk);
    cpu_rab.rd_reg_t( 1, 12'h138, rdat);

    cpu_rab.wr_reg_t( 1, 12'h130, {1'b1, 1'b0, 1'b0, 17'b0, 12'h78a});
    @(posedge clk);
    @(posedge clk);
    @(posedge clk);
    cpu_rab.rd_reg_t( 1, 12'h138, rdat);

    @(posedge clk);
    cpu_rab.rd_reg_t( 1, 12'h134, rdat);

    @(posedge clk);
    cpu_rab.wr_reg_t( 1, 12'h130, {1'b0, 1'b1, 1'b1, 17'b0, 12'h780});

    for(i=100; i<120; i=i+1) begin
        cpu_rab.wr_reg_t( 1, 12'h138, i);
    end

    @(posedge clk);
    cpu_rab.wr_reg_t( 1, 12'h130, {1'b1, 1'b0, 1'b1, 17'b0, 12'h780});

    @(posedge clk);
    for(i=100; i<120; i=i+1) begin
        cpu_rab.rd_reg_t( 3, 12'h138, rdat);
    end

    #10_000;
    rgrs.one_chk_done("register access done.");
end

initial begin
end

endmodule

